import React, { useState, useEffect } from 'react'
import { connect } from 'react-redux'
import { BASIC_STATE } from '@redux/reducers/basic'
import { setSMSSendTime } from '@redux/actions/basic'
import { awaitWrap } from '@js/tool'
import { sendSMSRequest } from '../ajax'
import style from './SMSInput.module.less'
import classNames from 'classnames'
import ClearBtn from './ClearBtn'
import { message } from 'antd'

interface Props {
  mobile: string
  validateCode: string
  dispatch: (o: any) => void
  onEnter: () => void
  sendTime: number
  setSendTime: (t: number) => void
}

interface BtnProps {
  mobile: string
  sendTime: number
  setSendTime: (t: number) => void
}

// 计算倒计时
function computeTime (t: number): number {
  if (t === 0) {
    return 0
  }
  const n = Date.now()
  const r = 60 - Math.floor((n - t) / 1000)
  if (r > 0) {
    return r
  }
  return 0
}

// 循环计时
function loopTime (time: number, setTime: (t: number) => void): void {
  const t = computeTime(time)
  setTime(t)
  if (t !== 0) {
    setTimeout(() => {
      loopTime(time, setTime)
    }, 1000)
  }
}

// 发送短信
async function sendSMS (sendable: boolean, mobile: string, setSendTime: (t: number) => void): Promise<void> {
  if (!sendable) {
    return undefined
  }
  const hide = message.loading('发送中', 120)
  const [e] = await awaitWrap(sendSMSRequest(mobile))
  hide()
  if (e === null) {
    setSendTime(Date.now())
  }
}

function Btn ({ mobile, sendTime, setSendTime }: BtnProps): React.ReactElement {
  const [sendable, setSendable] = useState(false)
  const [time, setTime] = useState(0)
  useEffect(() => {
    setSendable(mobile.length !== 0 && /^1\d{10}$/.test(mobile) && time <= 0)
  }, [mobile, time])
  useEffect(() => {
    loopTime(sendTime, setTime)
  }, [sendTime])
  const name = classNames(style.btn, { [style.active]: sendable })
  return (
    <button className={name} onClick={async () => await sendSMS(sendable, mobile, setSendTime)}>
      {time === 0 ? '发送验证码' : `${time}秒`}
    </button>
  )
}

// 清除输入
function clearCode (dispatch: (o: any) => void, setClearVisible: (v: boolean) => void): void {
  dispatch({ type: 'validateCode', data: '' })
  dispatch({ type: 'validateCodeError', data: '' })
  setClearVisible(false)
}

// 监听回车键事件
function enterHandle (e: React.KeyboardEvent, onEnter: () => void): void {
  const { keyCode, which, charCode } = e
  if (keyCode === 13 || which === 13 || charCode === 13) {
    onEnter()
  }
}

function Main ({ mobile, validateCode, dispatch, onEnter, sendTime, setSendTime }: Props): React.ReactElement {
  const [visible, setVisible] = useState(false)
  useEffect(() => {
    if (validateCode.length > 0) {
      setVisible(true)
    } else if (validateCode.length === 0 && visible) {
      setVisible(false)
    }
  }, [validateCode])
  return (
    <div className={style.container}>
      <div className={style['input-block']}>
        <input type="text" className={style.input} placeholder='请输入验证码' value={validateCode} autoComplete='off' onChange={e => dispatch({ type: 'validateCode', data: e.target.value })} maxLength={4} onKeyPress={e => enterHandle(e, onEnter)} />
        <ClearBtn visible={visible} onClick={() => clearCode(dispatch, setVisible)} />
      </div>
      <Btn mobile={mobile} sendTime={sendTime} setSendTime={setSendTime} />
    </div>
  )
}

export default connect(
  (state: { basic: BASIC_STATE }) => {
    return {
      sendTime: state.basic.SMSSendTime
    }
  },
  (dispatch) => {
    return {
      setSendTime: (t: number) => dispatch(setSMSSendTime(t))
    }
  }
)(Main)
